using DocumentCreationSystem.Models;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using Microsoft.Extensions.Logging;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

// 使用别名解决命名冲突
using DocModel = DocumentCreationSystem.Models.Document;
using OpenXmlDoc = DocumentFormat.OpenXml.Wordprocessing.Document;

namespace DocumentCreationSystem.Services;

/// <summary>
/// 文档服务实现
/// </summary>
public class DocumentService : IDocumentService
{
    private readonly IDataStorageService _dataStorage;
    private readonly ILogger<DocumentService> _logger;
    private readonly IProjectService _projectService;
    private readonly IVectorService _vectorService;

    public DocumentService(
        IDataStorageService dataStorage,
        ILogger<DocumentService> logger,
        IProjectService projectService,
        IVectorService vectorService)
    {
        _dataStorage = dataStorage;
        _logger = logger;
        _projectService = projectService;
        _vectorService = vectorService;
    }

    public async Task<DocModel> CreateDocumentAsync(int projectId, string fileName, string? content = null)
    {
        try
        {
            var project = await _projectService.GetProjectAsync(projectId);
            if (project == null)
            {
                throw new ArgumentException($"项目 {projectId} 不存在");
            }

            // 确保文件名有正确的扩展名
            if (!fileName.EndsWith(".docx", StringComparison.OrdinalIgnoreCase))
            {
                fileName += ".docx";
            }

            // 生成相对路径（使用中文文件夹名称）
            var relativePath = Path.Combine("文档", fileName);
            var fullPath = Path.Combine(project.RootPath, relativePath);

            // 确保目录存在
            var directory = Path.GetDirectoryName(fullPath);
            if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
            {
                Directory.CreateDirectory(directory);
            }

            // 创建docx文件
            await CreateDocxFileAsync(fullPath, content ?? "");

            // 创建文档记录
            var document = new DocModel
            {
                ProjectId = projectId,
                FileName = fileName,
                RelativePath = relativePath,
                Format = "docx",
                FileSize = new FileInfo(fullPath).Length,
                CreatedAt = DateTime.Now,
                UpdatedAt = DateTime.Now,
                FileModifiedAt = File.GetLastWriteTime(fullPath),
                WordCount = CountWords(content ?? ""),
                Status = "Active"
            };

            await _dataStorage.CreateDocumentAsync(document);

            _logger.LogInformation($"创建文档成功: {fileName}");
            return document;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, $"创建文档失败: {fileName}");
            throw;
        }
    }

    public async Task<bool> SaveDocumentAsync(int documentId, string content)
    {
        try
        {
            var document = await GetDocumentAsync(documentId);
            if (document == null)
            {
                _logger.LogWarning($"文档 {documentId} 不存在");
                return false;
            }

            var fullPath = GetDocumentFullPath(document);
            
            // 保存到docx文件
            await SaveToDocxFileAsync(fullPath, content);

            // 更新文档信息
            document.UpdatedAt = DateTime.Now;
            document.FileModifiedAt = File.GetLastWriteTime(fullPath);
            document.FileSize = new FileInfo(fullPath).Length;
            document.WordCount = CountWords(content);

            await _dataStorage.UpdateDocumentAsync(document);

            _logger.LogInformation($"保存文档成功: {document.FileName}");
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, $"保存文档失败: {documentId}");
            return false;
        }
    }

    public async Task<string> ReadDocumentAsync(int documentId)
    {
        try
        {
            var document = await GetDocumentAsync(documentId);
            if (document == null)
            {
                throw new ArgumentException($"文档 {documentId} 不存在");
            }

            var fullPath = GetDocumentFullPath(document);
            if (!File.Exists(fullPath))
            {
                throw new FileNotFoundException($"文档文件不存在: {fullPath}");
            }

            return await ReadFromDocxFileAsync(fullPath);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, $"读取文档失败: {documentId}");
            throw;
        }
    }

    public async Task<DocModel?> GetDocumentAsync(int documentId)
    {
        return await _dataStorage.GetDocumentAsync(documentId);
    }

    public async Task<List<DocModel>> GetProjectDocumentsAsync(int projectId)
    {
        var documents = await _dataStorage.GetDocumentsAsync(projectId);
        return documents.Where(d => d.Status == "Active")
                       .OrderBy(d => d.FileName)
                       .ToList();
    }

    public async Task<bool> DeleteDocumentAsync(int documentId)
    {
        try
        {
            var document = await GetDocumentAsync(documentId);
            if (document == null)
            {
                return false;
            }

            // 标记为已删除而不是物理删除
            document.Status = "Deleted";
            document.UpdatedAt = DateTime.Now;

            await _dataStorage.UpdateDocumentAsync(document);

            _logger.LogInformation($"删除文档成功: {document.FileName}");
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, $"删除文档失败: {documentId}");
            return false;
        }
    }

    public async Task<bool> UpdateDocumentAsync(DocModel document)
    {
        try
        {
            document.UpdatedAt = DateTime.Now;
            await _dataStorage.UpdateDocumentAsync(document);
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, $"更新文档失败: {document.Id}");
            return false;
        }
    }

    public int CountWords(string content)
    {
        if (string.IsNullOrWhiteSpace(content))
            return 0;

        // 移除HTML标签和特殊字符
        var cleanText = Regex.Replace(content, @"<[^>]+>", "");
        cleanText = Regex.Replace(cleanText, @"\s+", " ");

        // 中文字符计数
        var chineseChars = Regex.Matches(cleanText, @"[\u4e00-\u9fff]").Count;
        
        // 英文单词计数
        var englishWords = Regex.Matches(cleanText, @"\b[a-zA-Z]+\b").Count;

        return chineseChars + englishWords;
    }

    public async Task<bool> IsDocumentModifiedAsync(int documentId)
    {
        var document = await GetDocumentAsync(documentId);
        if (document == null)
            return false;

        var fullPath = GetDocumentFullPath(document);
        if (!File.Exists(fullPath))
            return false;

        var fileModifiedTime = File.GetLastWriteTime(fullPath);
        return fileModifiedTime > document.FileModifiedAt;
    }

    public async Task<string> GetDocumentFullPathAsync(DocModel document)
    {
        var project = await _dataStorage.GetProjectAsync(document.ProjectId);
        return project != null ? Path.Combine(project.RootPath, document.RelativePath) : document.RelativePath;
    }

    public string GetDocumentFullPath(DocModel document)
    {
        // 这个方法需要同步访问，暂时返回相对路径
        // 建议使用 GetDocumentFullPathAsync 方法
        return document.RelativePath;
    }

    public async Task<DocModel?> ImportDocumentAsync(int projectId, string filePath)
    {
        try
        {
            if (!File.Exists(filePath))
            {
                throw new FileNotFoundException($"文件不存在: {filePath}");
            }

            var fileName = Path.GetFileName(filePath);
            var content = await ReadFromDocxFileAsync(filePath);

            return await CreateDocumentAsync(projectId, fileName, content);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, $"导入文档失败: {filePath}");
            return null;
        }
    }

    public async Task<bool> ExportDocumentAsync(int documentId, string exportPath, string format = "docx")
    {
        try
        {
            var document = await GetDocumentAsync(documentId);
            if (document == null)
                return false;

            var content = await ReadDocumentAsync(documentId);
            var fullExportPath = Path.Combine(exportPath, document.FileName);

            if (format.ToLower() == "docx")
            {
                await CreateDocxFileAsync(fullExportPath, content);
            }
            else
            {
                await File.WriteAllTextAsync(fullExportPath, content, Encoding.UTF8);
            }

            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, $"导出文档失败: {documentId}");
            return false;
        }
    }

    #region 私有方法

    private async Task CreateDocxFileAsync(string filePath, string content)
    {
        using var document = WordprocessingDocument.Create(filePath, WordprocessingDocumentType.Document);
        var mainPart = document.AddMainDocumentPart();
        mainPart.Document = new OpenXmlDoc();
        var body = mainPart.Document.AppendChild(new Body());

        if (!string.IsNullOrEmpty(content))
        {
            var paragraphs = content.Split('\n', StringSplitOptions.RemoveEmptyEntries);
            foreach (var paragraphText in paragraphs)
            {
                var paragraph = new Paragraph();
                var run = new Run();
                run.AppendChild(new Text(paragraphText));
                paragraph.AppendChild(run);
                body.AppendChild(paragraph);
            }
        }
        else
        {
            // 创建空段落
            var paragraph = new Paragraph();
            var run = new Run();
            run.AppendChild(new Text(""));
            paragraph.AppendChild(run);
            body.AppendChild(paragraph);
        }

        await Task.CompletedTask;
    }

    private async Task SaveToDocxFileAsync(string filePath, string content)
    {
        using var document = WordprocessingDocument.Open(filePath, true);
        var body = document.MainDocumentPart?.Document?.Body;
        
        if (body != null)
        {
            body.RemoveAllChildren();
            
            var paragraphs = content.Split('\n', StringSplitOptions.RemoveEmptyEntries);
            foreach (var paragraphText in paragraphs)
            {
                var paragraph = new Paragraph();
                var run = new Run();
                run.AppendChild(new Text(paragraphText));
                paragraph.AppendChild(run);
                body.AppendChild(paragraph);
            }
        }

        await Task.CompletedTask;
    }

    private async Task<string> ReadFromDocxFileAsync(string filePath)
    {
        using var document = WordprocessingDocument.Open(filePath, false);
        var body = document.MainDocumentPart?.Document?.Body;
        
        if (body == null)
            return string.Empty;

        var content = new StringBuilder();
        foreach (var paragraph in body.Elements<Paragraph>())
        {
            content.AppendLine(paragraph.InnerText);
        }

        await Task.CompletedTask;
        return content.ToString();
    }

    #endregion

    #region 向量化相关方法

    public async Task<bool> VectorizeDocumentAsync(int documentId)
    {
        try
        {
            var document = await GetDocumentAsync(documentId);
            if (document == null)
                return false;

            var content = await ReadDocumentAsync(documentId);
            if (string.IsNullOrWhiteSpace(content))
                return false;

            var metadata = new Dictionary<string, object>
            {
                ["file_name"] = document.FileName,
                ["project_id"] = document.ProjectId,
                ["created_at"] = document.CreatedAt,
                ["word_count"] = document.WordCount
            };

            var chunks = _vectorService.SplitTextIntoChunks(content);
            var vectorRecords = await _vectorService.AddDocumentVectorsAsync(documentId, chunks);
            var vectorId = vectorRecords.FirstOrDefault()?.VectorId ?? Guid.NewGuid().ToString();

            // 更新文档的向量信息
            document.VectorId = vectorId;
            document.IsVectorized = true;
            await UpdateDocumentAsync(document);

            _logger.LogInformation($"文档向量化完成: {document.FileName}");
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, $"文档向量化失败: {documentId}");
            return false;
        }
    }

    public async Task<bool> UpdateDocumentVectorAsync(int documentId)
    {
        try
        {
            var document = await GetDocumentAsync(documentId);
            if (document == null || string.IsNullOrEmpty(document.VectorId))
                return false;

            var content = await ReadDocumentAsync(documentId);
            if (string.IsNullOrWhiteSpace(content))
                return false;

            var metadata = new Dictionary<string, object>
            {
                ["file_name"] = document.FileName,
                ["project_id"] = document.ProjectId,
                ["updated_at"] = DateTime.Now,
                ["word_count"] = CountWords(content)
            };

            var chunks = _vectorService.SplitTextIntoChunks(content);
            var success = await _vectorService.UpdateDocumentVectorsAsync(document.Id, chunks);

            if (success)
            {
                document.WordCount = CountWords(content);
                await UpdateDocumentAsync(document);
                _logger.LogInformation($"文档向量更新完成: {document.FileName}");
            }

            return success;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, $"文档向量更新失败: {documentId}");
            return false;
        }
    }

    public async Task<bool> RemoveDocumentVectorAsync(int documentId)
    {
        try
        {
            var document = await GetDocumentAsync(documentId);
            if (document == null || string.IsNullOrEmpty(document.VectorId))
                return false;

            var success = await _vectorService.DeleteDocumentVectorsAsync(document.Id);

            if (success)
            {
                document.VectorId = null;
                document.IsVectorized = false;
                await UpdateDocumentAsync(document);
                _logger.LogInformation($"文档向量删除完成: {document.FileName}");
            }

            return success;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, $"文档向量删除失败: {documentId}");
            return false;
        }
    }

    public async Task<DocModel?> GetDocumentByPathAsync(string filePath)
    {
        try
        {
            // 标准化路径
            var normalizedPath = Path.GetFullPath(filePath);

            // 获取所有项目的文档
            var allProjects = await _dataStorage.GetProjectsAsync();
            var documents = new List<DocModel>();
            foreach (var project in allProjects)
            {
                var projectDocs = await _dataStorage.GetDocumentsAsync(project.Id);
                documents.AddRange(projectDocs.Where(d => d.Status == "Active"));
            }

            foreach (var doc in documents)
            {
                var docFullPath = Path.GetFullPath(GetDocumentFullPath(doc));
                if (string.Equals(docFullPath, normalizedPath, StringComparison.OrdinalIgnoreCase))
                {
                    return doc;
                }
            }

            return null;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, $"根据路径查找文档失败: {filePath}");
            return null;
        }
    }

    public async Task<bool> UpdateDocumentFromFileAsync(int documentId)
    {
        try
        {
            var document = await GetDocumentAsync(documentId);
            if (document == null)
                return false;

            var fullPath = GetDocumentFullPath(document);
            if (!File.Exists(fullPath))
                return false;

            // 检查文件是否已修改
            var fileModifiedTime = File.GetLastWriteTime(fullPath);
            if (fileModifiedTime <= document.FileModifiedAt)
                return true; // 文件未修改

            // 读取文件内容
            var content = await ReadFromDocxFileAsync(fullPath);

            // 更新文档信息
            document.UpdatedAt = DateTime.Now;
            document.FileModifiedAt = fileModifiedTime;
            document.FileSize = new FileInfo(fullPath).Length;
            document.WordCount = CountWords(content);

            await UpdateDocumentAsync(document);

            // 如果文档已向量化，更新向量
            if (document.IsVectorized && !string.IsNullOrEmpty(document.VectorId))
            {
                await UpdateDocumentVectorAsync(documentId);
            }

            _logger.LogInformation($"从文件更新文档完成: {document.FileName}");
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, $"从文件更新文档失败: {documentId}");
            return false;
        }
    }

    public async Task<bool> MarkDocumentAsDeletedAsync(int documentId)
    {
        try
        {
            var document = await GetDocumentAsync(documentId);
            if (document == null)
                return false;

            // 删除向量
            if (document.IsVectorized && !string.IsNullOrEmpty(document.VectorId))
            {
                await RemoveDocumentVectorAsync(documentId);
            }

            // 标记为已删除
            document.Status = "Deleted";
            document.UpdatedAt = DateTime.Now;
            await UpdateDocumentAsync(document);

            _logger.LogInformation($"文档标记为已删除: {document.FileName}");
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, $"标记文档为已删除失败: {documentId}");
            return false;
        }
    }

    #endregion
}
